package com.example.springaiollamademo.service;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import reactor.core.publisher.Flux;

/**
 * 聊天服务类
 * @author 张飞
 * @version 1.0
 * @since 2025-12-01
 */
@Service
public class ChatService {

    private static final Logger logger = LoggerFactory.getLogger(ChatService.class);
    
    private final ChatClient chatClient;

    public ChatService(ChatClient.Builder chatClient) {
        logger.info("ChatService初始化，创建ChatClient实例");
        this.chatClient = chatClient.build();
        logger.info("ChatService初始化完成");
    }

    /**
     * 发送消息到Ollama并获取响应
     * @param prompt 用户输入的问题
     * @return Ollama的响应
     */
    public String chat(String prompt) {
        logger.info("ChatService.chat() 方法开始执行");
        logger.info("输入参数: prompt=[{}]", prompt);
        
        if (prompt == null || prompt.trim().isEmpty()) {
            logger.warn("输入参数验证失败: prompt为空");
            throw new IllegalArgumentException("问题不能为空");
        }
        
        try {
            logger.info("开始调用Ollama服务");
            logger.debug("构建ChatClient请求: user prompt");
            
            String response = this.chatClient.prompt()
                    .user(prompt)
                    .call()
                    .content();
                    
            logger.info("Ollama服务调用成功，响应长度: {} 字符", response != null ? response.length() : 0);
            logger.debug("Ollama响应内容: [{}]", response);
            
            // 直接返回原始响应，不进行think内容过滤
            return response;
        } catch (Exception e) {
            logger.error("调用Ollama服务失败，错误信息: {}", e.getMessage(), e);
            throw new RuntimeException("调用Ollama服务失败: " + e.getMessage(), e);
        }
    }

    /**
     * 带有系统提示的聊天
     * @param prompt 用户输入的问题
     * @param systemMessage 系统提示信息
     * @return Ollama的响应
     */
    public String chatWithSystem(String prompt, String systemMessage) {
        logger.info("ChatService.chatWithSystem() 方法开始执行");
        logger.info("输入参数: prompt=[{}], systemMessage=[{}]", prompt, systemMessage);
        
        if (prompt == null || prompt.trim().isEmpty()) {
            logger.warn("输入参数验证失败: prompt为空");
            throw new IllegalArgumentException("问题不能为空");
        }
        
        try {
            logger.info("开始调用Ollama服务（带系统提示）");
            logger.debug("构建ChatClient请求: system + user prompt");
            
            String response = this.chatClient.prompt()
                    .system(systemMessage)
                    .user(prompt)
                    .call()
                    .content();
                    
            logger.info("Ollama服务调用成功，响应长度: {} 字符", response != null ? response.length() : 0);
            logger.debug("Ollama响应内容: [{}]", response);
            
            // 直接返回原始响应，不进行think内容过滤
            return response;
        } catch (Exception e) {
            logger.error("调用Ollama服务失败，错误信息: {}", e.getMessage(), e);
            throw new RuntimeException("调用Ollama服务失败: " + e.getMessage(), e);
        }
    }

    /**
     * 流式聊天 - 逐步输出响应
     * @param prompt 用户输入的问题
     * @param emitter SSE发射器
     */
    public void chatStream(String prompt, SseEmitter emitter) {
        logger.info("ChatService.chatStream() 方法开始执行");
        logger.info("输入参数: prompt=[{}]", prompt);
        
        if (prompt == null || prompt.trim().isEmpty()) {
            logger.warn("输入参数验证失败: prompt为空");
            try {
                emitter.send(SseEmitter.event().name("error").data("问题不能为空"));
                emitter.complete();
            } catch (Exception e) {
                logger.error("发送错误信息失败", e);
                emitter.completeWithError(e);
            }
            return;
        }
        
        // 异步处理流式响应
        CompletableFuture.runAsync(() -> {
            AtomicBoolean emitterCompleted = new AtomicBoolean(false);
            
            try {
                logger.info("开始异步调用Ollama流式服务");
                
                // 使用Spring AI的流式API
                Flux<String> responseFlux = this.chatClient.prompt()
                        .user(prompt)
                        .stream()
                        .content();
                
                logger.info("Ollama流式服务调用启动成功");
                
                // 订阅流式响应
                responseFlux.subscribe(
                    chunk -> {
                        if (emitterCompleted.get()) {
                            logger.debug("Emitter已完成，跳过数据块: [{}]", chunk);
                            return;
                        }
                        
                        try {
                            logger.debug("接收到流式数据块: [{}]", chunk);
                            // 直接发送原始数据块，不进行think内容过滤
                            emitter.send(SseEmitter.event()
                                .name("message")
                                .data(chunk));
                        } catch (Exception e) {
                            logger.error("发送流式数据失败", e);
                            if (!emitterCompleted.getAndSet(true)) {
                                emitter.completeWithError(e);
                            }
                        }
                    },
                    error -> {
                        logger.error("流式响应处理出错", error);
                        if (!emitterCompleted.getAndSet(true)) {
                            try {
                                emitter.send(SseEmitter.event()
                                    .name("error")
                                    .data("流式响应处理出错: " + error.getMessage()));
                                emitter.complete();
                            } catch (Exception e) {
                                logger.error("发送错误信息失败", e);
                                emitter.completeWithError(e);
                            }
                        }
                    },
                    () -> {
                        logger.info("流式响应处理完成");
                        if (!emitterCompleted.getAndSet(true)) {
                            try {
                                emitter.send(SseEmitter.event()
                                    .name("done")
                                    .data("流式响应完成"));
                                emitter.complete();
                            } catch (Exception e) {
                                logger.error("发送完成信息失败", e);
                                emitter.completeWithError(e);
                            }
                        }
                    }
                );
                
            } catch (Exception e) {
                logger.error("异步处理流式响应失败", e);
                if (!emitterCompleted.getAndSet(true)) {
                    try {
                        emitter.send(SseEmitter.event()
                            .name("error")
                            .data("异步处理失败: " + e.getMessage()));
                        emitter.complete();
                    } catch (Exception sendException) {
                        logger.error("发送异步处理错误信息失败", sendException);
                        emitter.completeWithError(sendException);
                    }
                }
            }
        });
    }

    /**
     * 带系统提示的流式聊天
     * @param prompt 用户输入的问题
     * @param systemMessage 系统提示信息
     * @param emitter SSE发射器
     */
    public void chatWithSystemStream(String prompt, String systemMessage, SseEmitter emitter) {
        logger.info("ChatService.chatWithSystemStream() 方法开始执行");
        logger.info("输入参数: prompt=[{}], systemMessage=[{}]", prompt, systemMessage);
        
        if (prompt == null || prompt.trim().isEmpty()) {
            logger.warn("输入参数验证失败: prompt为空");
            try {
                emitter.send(SseEmitter.event().name("error").data("问题不能为空"));
                emitter.complete();
            } catch (Exception e) {
                logger.error("发送错误信息失败", e);
                emitter.completeWithError(e);
            }
            return;
        }
        
        // 异步处理流式响应
        CompletableFuture.runAsync(() -> {
            AtomicBoolean emitterCompleted = new AtomicBoolean(false);
            
            try {
                logger.info("开始异步调用Ollama流式服务（带系统提示）");
                
                // 使用Spring AI的流式API
                Flux<String> responseFlux = this.chatClient.prompt()
                        .system(systemMessage)
                        .user(prompt)
                        .stream()
                        .content();
                
                logger.info("Ollama流式服务调用启动成功（带系统提示）");
                
                // 订阅流式响应
                responseFlux.subscribe(
                    chunk -> {
                        if (emitterCompleted.get()) {
                            logger.debug("Emitter已完成，跳过数据块: [{}]", chunk);
                            return;
                        }
                        
                        try {
                            logger.debug("接收到流式数据块: [{}]", chunk);
                            // 直接发送原始数据块，不进行think内容过滤
                            emitter.send(SseEmitter.event()
                                .name("message")
                                .data(chunk));
                        } catch (Exception e) {
                            logger.error("发送流式数据失败", e);
                            if (!emitterCompleted.getAndSet(true)) {
                                emitter.completeWithError(e);
                            }
                        }
                    },
                error -> {
                    logger.error("流式响应处理出错", error);
                    if (!emitterCompleted.getAndSet(true)) {
                        try {
                            emitter.send(SseEmitter.event()
                                .name("error")
                                .data("流式响应处理出错: " + error.getMessage()));
                            emitter.complete();
                        } catch (Exception e) {
                            logger.error("发送错误信息失败", e);
                            emitter.completeWithError(e);
                        }
                    }
                },
                () -> {
                    logger.info("流式响应处理完成");
                    if (!emitterCompleted.getAndSet(true)) {
                        try {
                            emitter.send(SseEmitter.event()
                                .name("done")
                                .data("流式响应完成"));
                            emitter.complete();
                        } catch (Exception e) {
                            logger.error("发送完成信息失败", e);
                            emitter.completeWithError(e);
                        }
                    }
                }
            );
                
            } catch (Exception e) {
                logger.error("异步处理流式响应失败", e);
                if (!emitterCompleted.getAndSet(true)) {
                    try {
                        emitter.send(SseEmitter.event()
                            .name("error")
                            .data("异步处理失败: " + e.getMessage()));
                        emitter.complete();
                    } catch (Exception sendException) {
                        logger.error("发送异步处理错误信息失败", sendException);
                        emitter.completeWithError(sendException);
                    }
                }
            }
        });
    }
    
    /**
     * 带系统提示的流式聊天
     * @param prompt 用户输入的问题
     * @param systemMessage 系统提示信息
     * @param callback 流式回调接口
     */
    public void chatWithSystemStream(String prompt, String systemMessage, StreamCallback callback) {
        logger.info("ChatService.chatWithSystemStream() 方法开始执行");
        logger.info("输入参数: prompt=[{}], systemMessage=[{}]", prompt, systemMessage);
        
        if (prompt == null || prompt.trim().isEmpty()) {
            logger.warn("输入参数验证失败: prompt为空");
            callback.onError(new IllegalArgumentException("问题不能为空"));
            return;
        }
        
        // 异步处理流式响应
        CompletableFuture.runAsync(() -> {
            try {
                logger.info("开始异步调用Ollama流式服务");
                
                // 使用Spring AI的流式API
                Flux<String> responseFlux = this.chatClient.prompt()
                        .system(systemMessage)
                        .user(prompt)
                        .stream()
                        .content();
                
                logger.info("Ollama流式服务调用启动成功");
                
                // 订阅流式响应
                responseFlux.subscribe(
                    chunk -> {
                        logger.debug("接收到流式数据块: [{}]", chunk);
                        // 直接发送原始数据块，不进行think内容过滤
                        callback.onChunk(chunk);
                    },
                    error -> {
                        logger.error("流式响应处理出错", error);
                        callback.onError(error);
                    },
                    () -> {
                        logger.info("流式响应处理完成");
                        callback.onComplete();
                    }
                );
                
            } catch (Exception e) {
                logger.error("异步处理流式响应失败", e);
                callback.onError(e);
            }
        });
    }
    
    /**
     * 流式回调接口
     */
    public interface StreamCallback {
        /**
         * 接收到数据块
         * @param chunk 数据块内容
         */
        void onChunk(String chunk);
        
        /**
         * 流式响应完成
         */
        void onComplete();
        
        /**
         * 发生错误
         * @param error 错误信息
         */
        void onError(Throwable error);
    }
}
